<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
  <title>BI Dashboard</title>
  <link href="https://fonts.googleapis.com/css?family=Poppins:400,500,600&display=swap" rel="stylesheet">
  <link href="https://fonts.googleapis.com/css?family=Inter:400,600&display=swap" rel="stylesheet">
  <link href="https://fonts.googleapis.com/css?family=Open+Sans:400&display=swap" rel="stylesheet">
  <script src="https://cdn.jsdelivr.net/npm/echarts@5.5.0/dist/echarts.min.js"></script>
  <style>
    :root {
      --primary-bg: #f7fafd;
      --card-bg: #fff;
      --shadow: 0 4px 24px 0 rgba(80, 120, 200, 0.07);
      --border: #e3e8f0;
      --blue: #4079ED;
      --deep-blue: #151D48;
      --gray: #425166;
      --light-green: #e8f7ee;
      --light-orange: #fff7e6;
      --light-red: #ffeaea;
      --green: #3CD856;
      --orange: #FF947A;
      --red: #FA5A7D;
      --black: #222;
      --title: #222b45;
      --subtitle: #7b8ca7;
      --table-header: #f3f6fa;
      --table-border: #e3e8f0;
      --table-hover: #eaf1fb;
      --table-selected: #dbeafe;
      --table-zebra: #f7fafd;
      --donut-label: #444A6D;
      --accent: #5b9fff;
    }
    html, body {
      margin: 0;
      padding: 0;
      font-family: 'Poppins', 'Inter', 'Open Sans', 'FangSong', Arial, sans-serif;
      background: var(--primary-bg);
      color: var(--black);
      min-height: 100vh;
      box-sizing: border-box;
    }
    .main-wrapper {
      max-width: 1400px;
      margin: 0 auto;
      padding: 32px 16px 48px 16px;
      display: flex;
      flex-direction: column;
      gap: 40px;
    }
    .part1, .part2, .part3 {
      display: flex;
      gap: 32px;
      width: 100%;
    }
    .performance-card, .channel-card, .data-card, .customer-card, .table-section {
      background: linear-gradient(135deg, #fafdff 0%, #f3f6fa 100%);
      border-radius: 22px;
      box-shadow: 0 6px 32px 0 rgba(80, 120, 200, 0.10), 0 1.5px 4px 0 rgba(80,120,200,0.04);
      border: 1.5px solid #e6eaf3;
      padding: 36px 32px 32px 32px;
      display: flex;
      flex-direction: column;
      min-width: 320px;
      box-sizing: border-box;
    }
    .performance-card { flex: 2; }
    .channel-card { flex: 1.2; min-width: 320px; }
    .data-card, .customer-card, .table-section { flex: 1 1 0; }
    .performance-title, .block-title, .table-title {
      font-size: 22px;
      font-weight: 600;
      color: var(--title);
      margin-bottom: 20px;
      letter-spacing: 0.5px;
      font-family: 'Poppins', 'Inter', Arial, sans-serif;
    }
    .stat-row {
      display: flex;
      gap: 24px;
      flex-wrap: nowrap;
      overflow-x: auto;
      margin-bottom: 0;
      width: 100%;
      box-sizing: border-box;
    }
    .stat-box {
      background: var(--light-green);
      border-radius: 18px;
      padding: 28px 32px 24px 24px;
      min-width: 220px;
      max-width: 260px;
      flex: 1 1 220px;
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      position: relative;
      box-shadow: 0 2px 8px 0 rgba(80, 120, 200, 0.04);
      border: 1.5px solid #e0f2e9;
      transition: box-shadow 0.2s;
      justify-content: center;
      box-sizing: border-box;
      overflow: hidden;
      margin-bottom: 0;
    }
    .stat-box.orange { background: var(--light-orange); border-color: #ffe1b2; }
    .stat-box.red { background: var(--light-red); border-color: #ffd6d6; }
    .stat-icon {
      width: 40px;
      height: 40px;
      border-radius: 50%;
      display: flex;
      align-items: center;
      justify-content: center;
      margin-bottom: 8px;
      background: var(--green);
      box-shadow: 0 2px 8px 0 rgba(60, 216, 86, 0.08);
      font-size: 22px;
      color: #fff;
      flex-shrink: 0;
    }
    .stat-icon.orange { background: var(--orange); }
    .stat-icon.red { background: var(--red); }
    .stat-value {
      font-size: clamp(22px, 4vw, 36px);
      font-weight: 700;
      color: var(--deep-blue);
      margin-bottom: 2px;
      letter-spacing: 1px;
      text-align: left;
      word-break: break-all;
      max-width: 100%;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      font-family: 'Poppins', 'Inter', Arial, sans-serif;
    }
    .stat-label {
      font-size: clamp(12px, 2vw, 16px);
      font-weight: 500;
      color: var(--blue);
      margin-bottom: 2px;
      letter-spacing: 0.2px;
      text-align: left;
      max-width: 100%;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      font-family: 'Poppins', 'Inter', Arial, sans-serif;
    }
    .stat-desc {
      font-size: clamp(11px, 2vw, 15px);
      font-weight: 500;
      color: var(--gray);
      margin-bottom: 0;
      text-align: left;
      max-width: 100%;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      font-family: 'Poppins', 'Inter', Arial, sans-serif;
    }
    .block-title { margin-bottom: 20px; }
    .chart-row {
      display: flex;
      gap: 16px;
      align-items: center;
      flex-wrap: wrap;
    }
    .echart-box {
      width: 100%;
      min-width: 240px;
      height: 260px;
      max-width: 100%;
      margin-bottom: 16px;
      background: #f7fafd;
      border-radius: 16px;
      box-shadow: 0 2px 8px 0 rgba(80, 120, 200, 0.04);
      box-sizing: border-box;
      margin-bottom: 16px;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    .donut-legend {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      gap: 8px;
      margin-left: 0;
      font-size: 13px;
      margin-top: 0;
    }
    .donut-legend-item {
      display: flex;
      align-items: center;
      gap: 6px;
      font-size: 13px;
      color: var(--donut-label);
      font-weight: 500;
      white-space: nowrap;
      margin-bottom: 0;
    }
    .donut-dot {
      width: 12px;
      height: 12px;
      border-radius: 50%;
      display: inline-block;
    }
    .donut-dot.blue { background: #0095FF; }
    .donut-dot.green { background: #00E58F; }
    .donut-dot.purple { background: #884DFF; }
    .donut-dot.orange { background: #FF8900; }
    .donut-label-value {
      font-size: 13px;
      font-weight: 600;
      color: var(--black);
      margin-left: 4px;
    }
    .dropdown {
      position: relative;
      display: inline-block;
      margin-bottom: 18px;
      width: 100%;
      max-width: 220px;
    }
    .dropdown select {
      appearance: none;
      -webkit-appearance: none;
      -moz-appearance: none;
      background: #f3f6fa;
      border: 1.5px solid var(--border);
      border-radius: 6px;
      padding: 8px 32px 8px 32px;
      font-size: 15px;
      color: var(--deep-blue);
      font-family: 'Poppins', 'Inter', Arial, sans-serif;
      outline: none;
      cursor: pointer;
      transition: border 0.2s;
      width: 100%;
      min-width: 0;
    }
    .dropdown:after {
      content: '\25BC';
      position: absolute;
      right: 12px;
      top: 50%;
      transform: translateY(-50%);
      color: var(--subtitle);
      pointer-events: none;
      font-size: 13px;
    }
    .dropdown-option-icon {
      display: inline-block;
      vertical-align: middle;
      margin-right: 6px;
      width: 16px;
      height: 16px;
      margin-left: -18px;
      margin-bottom: 2px;
    }
    .table-section {
      min-width: 320px;
    }
    .table {
      width: 100%;
      border-collapse: separate;
      border-spacing: 0;
      background: var(--card-bg);
      border-radius: 16px;
      overflow: hidden;
      box-shadow: 0 2px 12px 0 rgba(80, 120, 200, 0.06);
      margin-bottom: 0;
      font-family: 'Poppins', 'Inter', Arial, sans-serif;
    }
    .table th, .table td {
      padding: 14px 16px;
      text-align: center;
      font-size: 15px;
      font-family: 'Poppins', 'Inter', Arial, sans-serif;
      color: var(--subtitle);
      background: none;
      transition: background 0.2s, color 0.2s;
    }
    .text-left { text-align: left !important; }
    .text-center { text-align: center !important; }
    .table th {
      background: var(--table-header);
      font-weight: 600;
      color: var(--deep-blue);
      border-bottom: 2px solid var(--border);
      font-family: 'Poppins', 'Inter', Arial, sans-serif;
    }
    .table tbody tr {
      transition: background 0.2s, box-shadow 0.2s;
    }
    .table tbody tr:nth-child(even) {
      background: var(--table-zebra);
    }
    .table tbody tr:hover {
      background: var(--table-hover);
      box-shadow: 0 2px 12px 0 rgba(91, 159, 255, 0.10);
      border-left: 4px solid var(--accent);
      color: var(--blue);
    }
    .table tbody tr.selected, .table tbody tr:active {
      background: var(--table-selected) !important;
      color: var(--blue);
      border-left: 4px solid var(--blue);
      box-shadow: 0 4px 16px 0 rgba(91, 159, 255, 0.13);
    }
    .table tbody tr.total-row td {
      font-weight: bold !important;
      color: var(--blue) !important;
      background: #eaf1fb !important;
      font-family: 'Poppins', 'Inter', Arial, sans-serif !important;
    }
    .table-row .badge {
      display: inline-block;
      min-width: 50px;
      padding: 4px 12px;
      border-radius: 8px;
      font-size: 15px;
      text-align: center;
      font-family: 'Open Sans', Arial, sans-serif;
      font-weight: 600;
    }
    .badge.blue { background: #F0F9FF; color: #0095FF; border: 1px solid #0095FF; }
    .badge.green { background: #F0FDF4; color: #00E58F; border: 1px solid #00E58F; }
    .badge.purple { background: #FBF1FF; color: #884DFF; border: 1px solid #884DFF; }
    .badge.orange { background: #FEF6E6; color: #FF8900; border: 1px solid #FF8900; }
    @media (max-width: 1200px) {
      .main-wrapper { padding: 16px 4px 32px 4px; gap: 24px; }
      .part1, .part2, .part3 { flex-direction: column; gap: 24px; }
      .performance-card, .channel-card, .data-card, .customer-card, .table-section { min-width: 0; }
      .channel-card .chart-row { flex-direction: column; align-items: flex-start; gap: 12px; }
      .donut-legend { margin-left: 0; margin-top: 8px; flex-wrap: wrap; }
      .stat-row { flex-wrap: wrap; gap: 16px; }
      .stat-box { min-width: 160px; max-width: 100%; padding: 16px 12px; }
    }
    @media (max-width: 800px) {
      .main-wrapper { padding: 8px 2px 16px 2px; gap: 12px; }
      .performance-card, .channel-card, .data-card, .customer-card, .table-section { padding: 12px 4px 10px 4px; min-width: 0; }
      .echart-box { height: 220px; min-width: 0; max-width: 380px; width: 100%; margin: 0 auto 16px auto; }
      .stat-row { flex-wrap: wrap; gap: 8px; }
      .stat-box { min-width: 160px; max-width: 100%; padding: 10px 6px; }
      .stat-value, .stat-label, .stat-desc { font-size: clamp(10px, 3vw, 18px); }
      .channel-card .chart-row { flex-direction: column; align-items: flex-start; gap: 12px; }
      .channel-card .echart-box { max-width: 340px; }
      .data-card .echart-box, .customer-card .echart-box {
        width: 99vw !important;
        max-width: 99vw !important;
        height: 300px !important;
      }
      .performance-title, .block-title, .table-title { font-size: 16px; font-family: 'Poppins', 'Inter', Arial, sans-serif; font-weight: 600; }
    }
    @media (max-width: 600px) {
      .part1, .part2 {
        flex-direction: column !important;
        gap: 12px !important;
      }
      .channel-card, .data-card, .customer-card {
        width: 100vw !important;
        max-width: 100vw !important;
        min-width: 0 !important;
        margin-bottom: 12px !important;
        padding: 8px 2px 8px 2px !important;
      }
      .channel-card .chart-row {
        flex-direction: column !important;
        align-items: stretch !important;
        gap: 8px !important;
      }
      .donut-legend {
        flex-direction: row !important;
        flex-wrap: wrap !important;
        justify-content: flex-start !important;
        margin: 0 0 8px 0 !important;
        gap: 8px !important;
      }
      .echart-box {
        width: 98vw !important;
        max-width: 98vw !important;
        min-width: 0 !important;
        height: 220px !important;
        margin: 0 auto 8px auto !important;
      }
    }
    @media (max-width: 430px) {
      html, body {
        font-size: 13px;
      }
      .main-wrapper {
        padding: 0 0 8px 0;
        gap: 4px;
      }
      .part1, .part2, .part3 {
        flex-direction: column;
        gap: 4px;
      }
      .performance-card, .channel-card, .data-card, .customer-card, .table-section {
        padding: 4px 0 2px 0;
        min-width: 0;
        width: 100vw;
        box-sizing: border-box;
      }
      .echart-box {
        height: 240px !important;
      }
      .stat-row {
        flex-direction: column;
        gap: 2px;
      }
      .stat-box {
        min-width: 80px;
        max-width: 100%;
        padding: 4px 2px;
      }
      .performance-title, .block-title, .table-title {
        font-size: 12px;
      }
      .donut-legend {
        font-size: 11px !important;
        gap: 4px !important;
      }
      .dropdown {
        max-width: 100vw;
        font-size: 12px;
      }
      .dropdown select {
        font-size: 12px;
        padding: 6px 24px 6px 16px;
      }
      .table-section, .table-scroll {
        width: 100vw !important;
        min-width: 0 !important;
        overflow-x: auto !important;
        display: block !important;
        min-height: 120px !important;
        overflow: visible !important;
      }
      .main-wrapper, .part3 {
        width: 100vw !important;
        display: block !important;
        overflow: visible !important;
      }
      .table {
        min-width: 320px !important;
        width: 100% !important;
        display: block !important;
        overflow: visible !important;
      }
      .table-scroll {
        max-height: 180px !important;
        overflow-y: auto !important;
      }
      .data-card .echart-box, .customer-card .echart-box {
        height: 240px !important;
      }
    }
    @media (max-width: 375px) {
      .echart-box {
        height: 140px;
      }
      .table {
        font-size: 11px;
        min-width: 320px !important;
      }
    }
    @media (max-width: 360px) {
      .echart-box {
        height: 120px;
      }
      .table {
        font-size: 10px;
        min-width: 320px !important;
      }
    }
    .channel-card .chart-row {
      display: flex;
      flex-direction: row;
      align-items: center;
      justify-content: flex-start;
      gap: 24px;
    }
    .channel-card .echart-box {
      margin-bottom: 0;
      margin-top: 0;
      align-self: center;
    }
    .table-scroll {
      max-height: 220px;
      overflow-y: auto;
      width: 100%;
      position: relative;
      margin-top: -1px;
    }
    .table-scroll::-webkit-scrollbar {
      display: none;
    }
    .table-scroll {
      -ms-overflow-style: none;
      scrollbar-width: none;
    }
    #customerTable thead th {
      position: sticky;
      top: 0;
      background: var(--table-header);
      z-index: 2;
    }
    #customerTable tfoot tr {
      position: sticky;
      bottom: 0;
      background: var(--table-header);
      z-index: 2;
    }
    .total-row td {
      font-weight: bold !important;
      color: var(--blue) !important;
      background: #eaf1fb !important;
      font-family: 'Poppins', 'Inter', Arial, sans-serif !important;
    }
    /* 针对数据统计和发货客户数图表，PC端宽度适中居中，移动端撑满 */
    .data-card .echart-box, .customer-card .echart-box {
      width: 100%;
      max-width: 700px;
      min-width: 0;
      height: 360px !important;
      margin: 0 auto 8px auto !important;
    }
    @media (max-width: 800px) {
      .data-card .echart-box, .customer-card .echart-box {
        width: 99vw !important;
        max-width: 99vw !important;
        height: 300px !important;
      }
    }
    @media (max-width: 430px) {
      .data-card .echart-box, .customer-card .echart-box {
        height: 240px !important;
      }
    }
    /* 客户排名与风险预警两个模块间距 */
    .part3 .table-section {
      margin-bottom: 16px;
    }
    .part3 .table-section:last-child {
      margin-bottom: 0;
    }
    /* 表格内容全部居中显示 */
    .table th, .table td {
      text-align: center !important;
    }
    /* 屏幕尺寸自适应表格字体 */
    @media (max-width: 800px) {
      .table {
        font-size: 13px !important;
      }
    }
    @media (max-width: 600px) {
      .table {
        font-size: 12px !important;
      }
    }
    @media (max-width: 430px) {
      .table {
        font-size: 11px !important;
      }
    }
    @media (max-width: 375px) {
      .table {
        font-size: 10px !important;
      }
    }
    /* 固定销售人员和完成情况列，表格横向滚动 */
    @media (max-width: 1100px) {
      #salesKpiTable {
        width: max-content;
      }
      #salesKpiTable th.left, #salesKpiTable td.left {
        position: sticky;
        left: 0;
        background: #fff;
        z-index: 10;
        min-width: 80px;
        white-space: nowrap;
        box-shadow: 2px 0 4px -2px #e3e8f0;
      }
      #salesKpiTable th.right, #salesKpiTable td.right {
        position: sticky;
        right: 0;
        background: #fff;
        z-index: 10;
        min-width: 90px;
        white-space: nowrap;
        box-shadow: -2px 0 4px -2px #e3e8f0;
      }
      #salesKpiTable th.left { background: #f3f6fa; }
      #salesKpiTable th.right { background: #f3f6fa; }
    }
    /* 风险预警表格样式优化 */
    #riskTable th, #riskTable td {
      font-size: 13px !important;
      padding: 6px 8px !important;
      min-width: 60px;
      max-width: 120px;
      white-space: nowrap;
    }
    #riskTable {
      min-width: 900px;
    }
    #riskTable tr {
      height: 32px;
    }
    @media (max-width: 600px) {
      #riskTable th, #riskTable td {
        font-size: 11px !important;
        padding: 4px 4px !important;
        min-width: 48px;
      }
      #riskTable {
        min-width: 700px;
      }
    }
  </style>
</head>
<body>
  <div class="main-wrapper">
    <div class="top-select-row" style="display:flex;gap:24px;align-items:center;margin-bottom:18px;">
      <div class="dropdown" style="max-width:200px;">
        <select id="departmentSelect2" data-staff-select="staffSelect2">
          <option value="">选择部门</option>
          <option value="sales">销售部</option>
          <option value="logistics">物流部</option>
          <option value="finance">财务部</option>
        </select>
      </div>
      <div class="dropdown" style="max-width:200px;">
        <select id="staffSelect2">
          <option value="">选择销售人员</option>
        </select>
      </div>
    </div>
    <!-- PART 1: Performance Data + Channel Distribution -->
    <div class="part1">
      <div class="performance-card">
        <div class="performance-title">业绩数据</div>
        <div class="stat-row">
          <div class="stat-box">
            <div class="stat-icon"></div>
            <div class="stat-value"></div>
            <div class="stat-label"></div>
            <div class="stat-desc"></div>
          </div>
          <div class="stat-box orange">
            <div class="stat-icon orange"></div>
            <div class="stat-value"></div>
            <div class="stat-label"></div>
            <div class="stat-desc"></div>
          </div>
          <div class="stat-box red">
            <div class="stat-icon red"></div>
            <div class="stat-value"></div>
            <div class="stat-label"></div>
            <div class="stat-desc"></div>
          </div>
        </div>
      </div>
      <div class="channel-card">
        <div class="block-title">渠道占比</div>
        <div class="chart-row">
          <div class="donut-legend">
            <div class="donut-legend-item"><span class="donut-dot blue"></span> 国际快递 <span class="donut-label-value">52.1%</span></div>
            <div class="donut-legend-item"><span class="donut-dot green"></span> 加拿大直航 <span class="donut-label-value">22.8%</span></div>
            <div class="donut-legend-item"><span class="donut-dot purple"></span> 美国空运 <span class="donut-label-value">13.9%</span></div>
            <div class="donut-legend-item"><span class="donut-dot orange"></span> 欧洲铁路 <span class="donut-label-value">11.2%</span></div>
          </div>
          <div id="donutChart" class="echart-box" style="max-width:260px;"></div>
        </div>
      </div>
    </div>
    <!-- PART 2: Data Statistics + Shipping Customer Count -->
    <div class="part2">
      <div class="data-card">
        <div class="block-title">周度分析</div>
        <div class="dropdown">
          <select id="dataStatSelect">
            <option value="weight">&#128230; 计费重</option>
            <option value="cbm">&#128207; CBM</option>
            <option value="customer_count">&#128202; 客户数</option>
          </select>
        </div>
        <div id="dataStatChart" class="echart-box"></div>
      </div>
      <div class="customer-card">
        <div class="block-title">月度分析</div>
        <div class="dropdown">
          <select id="customerCountSelect">
            <option value="weight">&#128230; 计费重</option>
            <option value="cbm">&#128207; CBM</option>
            <option value="customer_count">&#128202; 客户数</option>
          </select>
        </div>
        <div id="customerCountChart" class="echart-box"></div>
      </div>
    </div>
    <!-- PART 3: Customer Ranking + Risk Alerts -->
    <div class="part3">
      <div class="table-section">
        <div class="table-title">客户排名</div>
        <table class="table" id="customerTable">
          <thead>
            <tr>
              <th class="text-center">#</th>
              <th class="text-left">用户姓名</th>
              <th class="text-center">计费重</th>
              <th class="text-center">实际重量</th>
              <th class="text-center">CBM</th>
              <th class="text-center">泡比</th>
            </tr>
          </thead>
          <tfoot id="customerTableFoot"></tfoot>
        </table>
        <div class="table-scroll">
          <table class="table" style="margin:0;">
            <tbody id="customerTableBody"></tbody>
          </table>
        </div>
      </div>
      <div class="table-section">
        <div class="table-title">风险预警</div>
        <div class="table-scroll" style="max-height:280px;overflow-y:auto;overflow-x:auto;-ms-overflow-style:none;scrollbar-width:none;">
          <table class="table" id="riskTable" style="min-width:900px;margin:0;">
            <thead></thead>
            <tbody id="riskTableBody"></tbody>
          </table>
        </div>
      </div>
    </div>
    <!-- 销售考核完成情况模块，放在最底部，样式与上面一致 -->
    <div class="table-section">
      <div class="table-title">销售考核完成情况</div>
      <div style="overflow-x:auto;">
        <table class="table" id="salesKpiTable" style="min-width:900px; border-collapse:separate; border-spacing:0;">
          <thead>
            <tr>
              <th>销售人员</th>
              <th>1月</th><th>2月</th><th>3月</th><th>4月</th><th>5月</th><th>6月</th>
              <th>7月</th><th>8月</th><th>9月</th><th>10月</th><th>11月</th><th>12月</th>
              <th>25年考核指标</th>
              <th>当前累积总数</th>
              <th>完成情况</th>
            </tr>
          </thead>
          <tbody id="salesKpiTableBody"></tbody>
        </table>
      </div>
    </div>
  </div>
  <script>
    alert('script块已加载');
    (function() {
      console.log('IIFE执行');
      document.addEventListener('DOMContentLoaded', function() {
        console.log('DOMContentLoaded');
        var depSelect = document.getElementById('departmentSelect2');
        if (!depSelect) {
          console.error('找不到 id=departmentSelect2 的元素');
          return;
        }
        var staffSelectId = depSelect.getAttribute('data-staff-select');
        if (!staffSelectId) {
          console.error('departmentSelect2 没有 data-staff-select 属性');
          return;
        }
        var staffSelect = document.getElementById(staffSelectId);
        if (!staffSelect) {
          console.error('找不到 id=' + staffSelectId + ' 的元素');
          return;
        }
        var dataStatChart = document.getElementById('dataStatChart');
        if (!dataStatChart) {
          console.error('找不到 id=dataStatChart 的元素');
          return;
        }
        var dataStatSelect = document.getElementById('dataStatSelect');
        if (!dataStatSelect) {
          console.error('找不到 id=dataStatSelect 的元素');
          return;
        }
        var weeklyAnalysisChart = null;
        var departmentStaffMap = {};

        // 新增：通过API获取部门和销售人员
        function fetchDepartmentsAndStaff() {
          fetch('http://127.0.0.1:5001/api/shipments/active_salespersons')
            .then(res => res.json())
            .then(data => {
              departmentStaffMap = data || {};
              renderDepartmentOptions();
              renderStaffOptions();
            })
            .catch(err => {
              console.error('获取部门和销售人员失败:', err);
              departmentStaffMap = {};
              renderDepartmentOptions();
              renderStaffOptions();
            });
        }

        function renderDepartmentOptions() {
          depSelect.innerHTML = '<option value="">选择部门</option>';
          Object.keys(departmentStaffMap).forEach(dep => {
            var opt = document.createElement('option');
            opt.value = dep;
            opt.textContent = dep;
            depSelect.appendChild(opt);
          });
        }

        function renderStaffOptions() {
          staffSelect.innerHTML = '<option value="">选择销售人员</option>';
          var dep = depSelect.value;
          if (dep && departmentStaffMap[dep]) {
            departmentStaffMap[dep].forEach(staff => {
              var opt = document.createElement('option');
              opt.value = staff.value;
              opt.textContent = staff.label;
              staffSelect.appendChild(opt);
            });
          }
        }

        depSelect.addEventListener('change', function(e) {
          renderStaffOptions();
          // 重新加载周度分析数据
          setTimeout(function() {
            loadWeeklyAnalysisData();
          }, 100);
        });
        staffSelect.addEventListener('change', function() {
          loadWeeklyAnalysisData();
        });

        // 页面加载时拉取部门和销售人员
        fetchDepartmentsAndStaff();
        // 页面加载时初始化图表并加载全量数据
        initWeeklyAnalysisChart();
        loadWeeklyAnalysisData();
        
        // 新增：周度分析模块API调用和图表渲染
        function initWeeklyAnalysisChart() {
          if (!dataStatChart) {
            console.error('dataStatChart 未定义或未获取到 DOM 元素');
            return;
          }
          if (weeklyAnalysisChart) {
            weeklyAnalysisChart.dispose();
            weeklyAnalysisChart = null;
          }
          weeklyAnalysisChart = echarts.init(dataStatChart);
        }
        
        // 调用周度分析API
        function loadWeeklyAnalysisData() {
          if (!depSelect || !staffSelect || !dataStatSelect) {
            console.error('下拉框元素未定义');
            return;
          }
          var department = depSelect.value;
          var seller = staffSelect.value;
          var dataType = dataStatSelect.value;
          
          console.log('=== 周度分析API调用开始 ===');
          console.log('当前选择参数:');
          console.log('- department:', department);
          console.log('- seller:', seller);
          console.log('- dataType:', dataType);
          
          // 构建API请求URL
          var apiUrl = 'http://127.0.0.1:5001/api/shipments/weekly_analysis';
          var params = new URLSearchParams();
          if (department) params.append('department', department);
          if (seller) params.append('seller', seller);
          
          var fullUrl = apiUrl + '?' + params.toString();
          console.log('完整API URL:', fullUrl);
          console.log('请求参数:', params.toString());
          
          console.log('开始发送fetch请求...');
          
          fetch(fullUrl)
            .then(response => {
              console.log('收到响应:', response);
              console.log('响应状态:', response.status);
              console.log('响应状态文本:', response.statusText);
              console.log('响应头:', response.headers);
              
              if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
              }
              
              console.log('开始解析JSON...');
              return response.json();
            })
            .then(data => {
              console.log('=== 周度分析API响应数据 ===');
              console.log('原始响应数据:', data);
              console.log('数据类型:', typeof data);
              console.log('是否为数组:', Array.isArray(data));
              
              // 每次加载数据前都重新初始化图表，防止容器尺寸变化导致渲染异常
              initWeeklyAnalysisChart();
              if (data && typeof data === 'object' && data.code === 200 && Array.isArray(data.data) && data.data.length > 0) {
                renderWeeklyAnalysisChart(data.data, dataType);
              } else if (data && typeof data === 'object' && data.code !== 200) {
                renderErrorChart();
              } else {
                renderEmptyChart();
              }
            })
            .catch(error => {
              console.error('=== 周度分析API调用失败 ===');
              console.error('错误类型:', error.constructor.name);
              console.error('错误消息:', error.message);
              console.error('错误堆栈:', error.stack);
              renderErrorChart();
            });
          
          console.log('=== 周度分析API调用结束 ===');
        }
        
        // 渲染周度分析图表
        function renderWeeklyAnalysisChart(data, dataType) {
          // 每次渲染前都初始化，防止容器尺寸变化或实例丢失
          if (!weeklyAnalysisChart) {
            weeklyAnalysisChart = echarts.init(dataStatChart);
          }
          console.log('=== 开始渲染周度分析图表 ===');
          console.log('输入数据:', data);
          console.log('数据类型:', dataType);
          
          var xAxisData = data.map(item => item.pt_week);
          console.log('X轴数据:', xAxisData);
          
          var seriesData = data.map(item => {
            var value = 0;
            switch(dataType) {
              case 'weight':
                value = item.total_chargeable_weight || 0;
                break;
              case 'cbm':
                value = item.total_cbm || 0;
                break;
              case 'customer_count':
                value = item.customer_count || 0;
                break;
              default:
                value = 0;
            }
            console.log(`数据项 ${item.pt_week}:`, item, '提取值:', value);
            return value;
          });
          
          console.log('Y轴数据:', seriesData);
          
          var yAxisName = '';
          var title = '';
          switch(dataType) {
            case 'weight':
              yAxisName = '计费重 (kg)';
              title = '周度计费重分析';
              break;
            case 'cbm':
              yAxisName = 'CBM (m³)';
              title = '周度CBM分析';
              break;
            case 'customer_count':
              yAxisName = '客户数';
              title = '周度客户数分析';
              break;
          }
          
          console.log('图表标题:', title);
          console.log('Y轴名称:', yAxisName);
          
          var option = {
            title: {
              text: title,
              left: 'center',
              textStyle: {
                fontSize: 16,
                fontWeight: 'bold',
                color: '#222b45'
              }
            },
            tooltip: {
              trigger: 'axis',
              axisPointer: {
                type: 'shadow'
              }
            },
            grid: {
              left: '3%',
              right: '4%',
              bottom: '3%',
              containLabel: true
            },
            xAxis: {
              type: 'category',
              data: xAxisData,
              axisLabel: {
                color: '#7b8ca7'
              }
            },
            yAxis: {
              type: 'value',
              name: yAxisName,
              axisLabel: {
                color: '#7b8ca7'
              }
            },
            series: [{
              data: seriesData,
              type: 'bar',
              itemStyle: {
                color: '#4079ED'
              },
              emphasis: {
                itemStyle: {
                  color: '#5b9fff'
                }
              }
            }]
          };
          
          console.log('ECharts配置:', option);
          console.log('图表实例:', weeklyAnalysisChart);
          
          try {
            weeklyAnalysisChart.setOption(option);
            console.log('图表渲染成功');
          } catch (error) {
            console.error('图表渲染失败:', error);
          }
          
          console.log('=== 周度分析图表渲染完成 ===');
        }
        
        // 渲染空数据图表
        function renderEmptyChart() {
          var option = {
            title: {
              text: '暂无数据',
              left: 'center',
              top: 'middle',
              textStyle: {
                fontSize: 16,
                color: '#7b8ca7'
              }
            }
          };
          weeklyAnalysisChart.setOption(option);
        }
        
        // 渲染错误图表
        function renderErrorChart() {
          var option = {
            title: {
              text: '数据加载失败',
              left: 'center',
              top: 'middle',
              textStyle: {
                fontSize: 16,
                color: '#FA5A7D'
              }
            }
          };
          weeklyAnalysisChart.setOption(option);
        }
        
        // 监听数据类型选择变化
        dataStatSelect.addEventListener('change', function() {
          loadWeeklyAnalysisData();
        });

        // 月度分析相关变量
        var customerCountSelect = document.getElementById('customerCountSelect');
        var customerCountChartDiv = document.getElementById('customerCountChart');
        var monthlyAnalysisChart = null;

        // 初始化月度分析图表
        function initMonthlyAnalysisChart() {
          if (monthlyAnalysisChart) {
            monthlyAnalysisChart.dispose();
            monthlyAnalysisChart = null;
          }
          monthlyAnalysisChart = echarts.init(customerCountChartDiv);
        }

        // 渲染月度分析图表
        function renderMonthlyAnalysisChart(data, dataType) {
          if (!monthlyAnalysisChart) {
            monthlyAnalysisChart = echarts.init(customerCountChartDiv);
          }
          var xAxisData = data.map(item => item.pt_month);
          var seriesData = data.map(item => {
            var value = 0;
            switch(dataType) {
              case 'weight':
                value = item.total_chargeable_weight || 0;
                break;
              case 'cbm':
                value = item.total_cbm || 0;
                break;
              case 'customer_count':
                value = item.customer_count || 0;
                break;
              default:
                value = 0;
            }
            return value;
          });
          var yAxisName = '';
          var title = '';
          switch(dataType) {
            case 'weight':
              yAxisName = '计费重 (kg)';
              title = '月度计费重分析';
              break;
            case 'cbm':
              yAxisName = 'CBM (m³)';
              title = '月度CBM分析';
              break;
            case 'customer_count':
              yAxisName = '客户数';
              title = '月度客户数分析';
              break;
          }
          var option = {
            title: {
              text: title,
              left: 'center',
              textStyle: {
                fontSize: 16,
                fontWeight: 'bold',
                color: '#222b45'
              }
            },
            tooltip: {
              trigger: 'axis',
              axisPointer: {
                type: 'shadow'
              }
            },
            grid: {
              left: '3%',
              right: '4%',
              bottom: '3%',
              containLabel: true
            },
            xAxis: {
              type: 'category',
              data: xAxisData,
              axisLabel: {
                color: '#7b8ca7'
              }
            },
            yAxis: {
              type: 'value',
              name: yAxisName,
              axisLabel: {
                color: '#7b8ca7'
              }
            },
            series: [{
              data: seriesData,
              type: 'bar',
              itemStyle: {
                color: '#4079ED'
              },
              emphasis: {
                itemStyle: {
                  color: '#5b9fff'
                }
              }
            }]
          };
          try {
            monthlyAnalysisChart.setOption(option);
          } catch (error) {
            console.error('月度分析图表渲染失败:', error);
          }
        }

        // 渲染空数据图表
        function renderEmptyMonthlyChart() {
          if (!monthlyAnalysisChart) {
            monthlyAnalysisChart = echarts.init(customerCountChartDiv);
          }
          var option = {
            title: {
              text: '暂无数据',
              left: 'center',
              top: 'middle',
              textStyle: {
                fontSize: 16,
                color: '#7b8ca7'
              }
            }
          };
          monthlyAnalysisChart.setOption(option);
        }
        // 渲染错误图表
        function renderErrorMonthlyChart() {
          if (!monthlyAnalysisChart) {
            monthlyAnalysisChart = echarts.init(customerCountChartDiv);
          }
          var option = {
            title: {
              text: '数据加载失败',
              left: 'center',
              top: 'middle',
              textStyle: {
                fontSize: 16,
                color: '#FA5A7D'
              }
            }
          };
          monthlyAnalysisChart.setOption(option);
        }

        // 调用月度分析API
        function loadMonthlyAnalysisData() {
          if (!depSelect || !staffSelect || !customerCountSelect) {
            console.error('月度分析下拉框元素未定义');
            return;
          }
          var department = depSelect.value;
          var seller = staffSelect.value;
          var dataType = customerCountSelect.value;
          // 默认查询1-12月
          var apiUrl = 'http://127.0.0.1:5001/api/shipments/monthly_analysis';
          var params = new URLSearchParams();
          params.append('start_month', '01');
          params.append('end_month', '12');
          if (department) params.append('department', department);
          if (seller) params.append('seller', seller);
          var fullUrl = apiUrl + '?' + params.toString();
          fetch(fullUrl)
            .then(response => response.json())
            .then(data => {
              initMonthlyAnalysisChart();
              if (data && typeof data === 'object' && Array.isArray(data.data) && data.data.length > 0) {
                renderMonthlyAnalysisChart(data.data, dataType);
              } else {
                renderEmptyMonthlyChart();
              }
            })
            .catch(error => {
              renderErrorMonthlyChart();
            });
        }

        // 监听月度分析下拉框变化
        customerCountSelect.addEventListener('change', function() {
          loadMonthlyAnalysisData();
        });
        depSelect.addEventListener('change', function() {
          setTimeout(loadMonthlyAnalysisData, 100);
        });
        staffSelect.addEventListener('change', function() {
          loadMonthlyAnalysisData();
        });
        // 页面加载时初始化月度分析图表并加载全量数据
        initMonthlyAnalysisChart();
        loadMonthlyAnalysisData();

        // 客户排名相关变量
        var customerTableBody = document.getElementById('customerTableBody');
        var customerTableFoot = document.getElementById('customerTableFoot');

        // 渲染客户排名表格
        function renderCustomerRankingTable(data) {
          customerTableBody.innerHTML = '';
          customerTableFoot.innerHTML = '';
          if (!Array.isArray(data) || data.length === 0) {
            customerTableBody.innerHTML = '<tr><td colspan="6" style="color:#aaa;">暂无数据</td></tr>';
            return;
          }
          var total = {
            'total_chargeable_weight': 0,
            'total_actual_weight': 0,
            'total_cbm': 0,
            'volume_weight_radix': 0
          };
          data.forEach(function(row, idx) {
            var tr = document.createElement('tr');
            tr.innerHTML = `<td>${idx + 1}</td><td>${row['username']}</td><td>${Number(row['total_chargeable_weight']).toFixed(2)}</td><td>${Number(row['total_actual_weight']).toFixed(2)}</td><td>${Number(row['total_cbm']).toFixed(2)}</td><td>${Number(row['volume_weight_radix']).toFixed(2)}</td>`;
            customerTableBody.appendChild(tr);
            total['total_chargeable_weight'] += Number(row['total_chargeable_weight']);
            total['total_actual_weight'] += Number(row['total_actual_weight']);
            total['total_cbm'] += Number(row['total_cbm']);
            total['volume_weight_radix'] += Number(row['volume_weight_radix']);
          });
          // 总计行
          var totalRow = `<tr class="total-row"><td colspan="2">总计：</td><td>${total['total_chargeable_weight'].toFixed(2)}</td><td>${total['total_actual_weight'].toFixed(2)}</td><td>${(total['total_cbm']/data.length).toFixed(2)}</td><td>${(total['volume_weight_radix']/data.length).toFixed(2)}</td></tr>`;
          customerTableFoot.innerHTML = totalRow;
        }

        // 调用客户排名API
        function loadCustomerRankingData() {
          if (!depSelect || !staffSelect) {
            console.error('客户排名下拉框元素未定义');
            return;
          }
          var department = depSelect.value;
          var seller = staffSelect.value;
          var apiUrl = 'http://127.0.0.1:5001/api/shipments/customer_ranking';
          var params = new URLSearchParams();
          if (department) params.append('department', department);
          if (seller) params.append('seller', seller);
          var fullUrl = apiUrl + '?' + params.toString();
          fetch(fullUrl)
            .then(response => response.json())
            .then(data => {
              if (data && typeof data === 'object' && Array.isArray(data.data) && data.data.length > 0) {
                renderCustomerRankingTable(data.data);
              } else {
                renderCustomerRankingTable([]);
              }
            })
            .catch(error => {
              renderCustomerRankingTable([]);
            });
        }

        // 监听部门和销售人员下拉框变化
        depSelect.addEventListener('change', function() {
          setTimeout(loadCustomerRankingData, 100);
        });
        staffSelect.addEventListener('change', function() {
          loadCustomerRankingData();
        });
        // 页面加载时初始化客户排名表格
        loadCustomerRankingData();

        // 风险预警相关变量
        var riskTableBody = document.getElementById('riskTableBody');
        var riskTable = document.getElementById('riskTable');

        // 渲染风险预警表格（自定义表头和字段映射，支持横向滚动）
        function renderRiskAlertsTable(data) {
          var weeks = ['week_4', 'week_3', 'week_2', 'this_week', 'last_week'];
          var weekNames = ['上4周', '上3周', '上2周', '本周', '上周'];
          var thead = riskTable.querySelector('thead');
          if (thead) {
            thead.innerHTML = `<tr><th class=\"text-center\">#</th>${weekNames.map(w=>`<th>${w}</th>`).join('')}<th>环比率</th></tr>`;
          }
          riskTableBody.innerHTML = '';
          if (!Array.isArray(data) || data.length === 0) {
            riskTableBody.innerHTML = '<tr><td colspan="7" style="color:#aaa;">暂无数据</td></tr>';
            return;
          }
          data.forEach(function(row, idx) {
            var ratio = Number(row.ratio*100).toFixed(1);
            var ratioColor = ratio > 0 ? '#3CD856' : (ratio < 0 ? '#FA5A7D' : '#888');
            var ratioHtml = `<span style=\"font-weight:bold;color:${ratioColor};\">${ratio}%</span>`;
            var tr = document.createElement('tr');
            tr.innerHTML = `<td>${idx + 1}</td>${weeks.map(w=>`<td>${Number(row[w]||0).toFixed(2)}</td>`).join('')}<td>${ratioHtml}</td>`;
            riskTableBody.appendChild(tr);
          });
          // 横向滚动
          var riskTableSection = riskTable.closest('.table-section');
          if (riskTableSection) {
            riskTableSection.style.overflowX = 'auto';
          }
        }

        // 调用风险预警API
        function loadRiskAlertsData() {
          if (!depSelect || !staffSelect) {
            console.error('风险预警下拉框元素未定义');
            return;
          }
          var department = depSelect.value;
          var seller = staffSelect.value;
          var apiUrl = 'http://127.0.0.1:5001/api/shipments/risk_alerts_weekly';
          var params = new URLSearchParams();
          if (department) params.append('department', department);
          if (seller) params.append('seller', seller);
          var fullUrl = apiUrl + '?' + params.toString();
          fetch(fullUrl)
            .then(response => response.json())
            .then(data => {
              if (data && typeof data === 'object' && Array.isArray(data.data) && data.data.length > 0) {
                renderRiskAlertsTable(data.data);
              } else {
                renderRiskAlertsTable([]);
              }
            })
            .catch(error => {
              renderRiskAlertsTable([]);
            });
        }

        // 监听部门和销售人员下拉框变化
        depSelect.addEventListener('change', function() {
          setTimeout(loadRiskAlertsData, 100);
        });
        staffSelect.addEventListener('change', function() {
          loadRiskAlertsData();
        });
        // 页面加载时初始化风险预警表格
        loadRiskAlertsData();

        // 销售考核相关变量
        var salesKpiTableBody = document.getElementById('salesKpiTableBody');

        // 渲染销售考核表格
        function renderSalesKpiTable(data) {
          salesKpiTableBody.innerHTML = '';
          if (!Array.isArray(data) || data.length === 0) {
            salesKpiTableBody.innerHTML = '<tr><td colspan="16" style="color:#aaa;">暂无数据</td></tr>';
            return;
          }
          data.forEach(function(row) {
            var months = [];
            for (var i = 1; i <= 12; i++) {
              months.push(`<td>${Number(row['m'+i]||0).toFixed(2)}</td>`);
            }
            var finishRate = (row.finish_rate !== undefined && row.finish_rate !== null) ? (Number(row.finish_rate)*100).toFixed(1)+'%' : '-';
            var total = 0;
            for (var i = 1; i <= 12; i++) total += Number(row['m'+i]||0);
            salesKpiTableBody.innerHTML += `<tr><td>${row.salesperson_name}</td>${months.join('')}<td>${Number(row['2025total_target']||0).toFixed(2)}</td><td>${total.toFixed(2)}</td><td>${finishRate}</td></tr>`;
          });
        }

        // 调用销售考核API
        function loadSalesKpiData() {
          if (!depSelect || !staffSelect) {
            console.error('销售考核下拉框元素未定义');
            return;
          }
          var department = depSelect.value;
          var seller = staffSelect.value;
          var apiUrl = 'http://127.0.0.1:5001/api/shipments/sales_kpi';
          var params = new URLSearchParams();
          if (department) params.append('department', department);
          if (seller) params.append('seller', seller);
          var fullUrl = apiUrl + '?' + params.toString();
          fetch(fullUrl)
            .then(response => response.json())
            .then(data => {
              if (data && typeof data === 'object' && Array.isArray(data.data) && data.data.length > 0) {
                renderSalesKpiTable(data.data);
              } else {
                renderSalesKpiTable([]);
              }
            })
            .catch(error => {
              renderSalesKpiTable([]);
            });
        }

        // 监听部门和销售人员下拉框变化
        depSelect.addEventListener('change', function() {
          setTimeout(loadSalesKpiData, 100);
        });
        staffSelect.addEventListener('change', function() {
          loadSalesKpiData();
        });
        // 页面加载时初始化销售考核表格
        loadSalesKpiData();

        // 渠道占比相关变量
        var donutChartDiv = document.getElementById('donutChart');
        var donutChart = null;
        // 渲染渠道占比饼图（自动百分比，图例同步）
        function renderChannelPieChart(data) {
          if (!donutChartDiv) return;
          if (donutChart) {
            donutChart.dispose();
            donutChart = null;
          }
          donutChart = echarts.init(donutChartDiv);
          // 动态整理数据
          var pieData = (data || []).map(d => ({
            value: d.total_chargeable_weight,
            name: d.servicer_channel
          }));
          donutChart.setOption({
            tooltip: { trigger: 'item', formatter: '{b}: {c}kg ({d}%)' },
            legend: { show: false },
            series: [{
              name: '渠道占比', type: 'pie', radius: ['40%', '70%'],
              label: { show: true, formatter: '{b}: {d}%' },
              data: pieData
            }]
          });
          // 图例同步显示百分比
          var legendDiv = document.querySelector('.donut-legend');
          if (legendDiv) {
            legendDiv.innerHTML = '';
            var total = pieData.reduce((sum, d) => sum + d.value, 0) || 1;
            pieData.forEach(item => {
              var percent = ((item.value / total) * 100).toFixed(1);
              legendDiv.innerHTML += `<div class="donut-legend-item"><span class="donut-dot" style="background:#4079ED"></span> ${item.name} <span class="donut-label-value">${percent}%</span></div>`;
            });
          }
        }
        // 调用渠道占比API
        function loadChannelRatioData() {
          if (!depSelect || !staffSelect) return;
          var department = depSelect.value;
          var seller = staffSelect.value;
          var apiUrl = 'http://127.0.0.1:5001/api/shipments/channel_ratio';
          var params = new URLSearchParams();
          if (department) params.append('department', department);
          if (seller) params.append('seller', seller);
          var fullUrl = apiUrl + '?' + params.toString();
          fetch(fullUrl)
            .then(response => response.json())
            .then(data => {
              if (data && typeof data === 'object' && Array.isArray(data.data)) {
                renderChannelPieChart(data.data);
              } else {
                renderChannelPieChart([]);
              }
            })
            .catch(error => {
              renderChannelPieChart([]);
            });
        }
        // 监听部门和销售人员下拉框变化
        depSelect.addEventListener('change', function() {
          setTimeout(loadChannelRatioData, 100);
        });
        staffSelect.addEventListener('change', function() {
          loadChannelRatioData();
        });
        // 页面加载时初始化渠道占比饼图
        loadChannelRatioData();

      });
    })();
  </script>
</body>
</html> 